from flask import Blueprint, request
from AuthComponent import auth_required
from app import db_mongo
from utils import respond, ERRORCODES
from statistics import mean, variance
from config import Config
import os
from openai import OpenAI
# from .models import Data

bp = Blueprint("DataManager", __name__, url_prefix="/data/")


@auth_required()
@bp.route("/upload", methods=["POST"])
def upload():
    req_data = request.get_json()
    required_params = ("device_id", "time", "data")
    if not all(param in req_data for param in required_params):
        return respond(None, "缺少必要参数。", ERRORCODES.BAD_REQUEST)

    environment_params = (
        "temperature",
        "humidity",
        "fresh_air",
        "ozone",
        "nitro_dio",
        "methanal",
        "pm2_5",
        "carb_momo",
        "bacteria",
        "radon",
    )
    if not all(param in req_data["data"] for param in environment_params):
        return respond(None, "缺少环境数据", ERRORCODES.BAD_REQUEST)

    try:
        collection = db_mongo["EnvData"]
        req_data["processed"] = False
        collection.insert_one(req_data)

        # 检查数据量并计算统计值
        data_count = collection.count_documents(
            {"device_id": req_data["device_id"], "processed": False}
        )
        if data_count >= Config.STAT_COUNTER:
            print(f"数据量达到{Config.STAT_COUNTER}条，开始计算统计值。")
            # 获取最近数据
            recent_data = list(
                collection.find({"device_id": req_data["device_id"]})
                .sort("time", -1)
                .limit(Config.STAT_COUNTER)
            )

            # 提取各项环境数据
            env_data = {param: [] for param in environment_params}
            for record in recent_data:
                for param in environment_params:
                    env_data[param].append(float(record["data"][param]))
                record["processed"] = True

            # 计算统计值
            stats = {}
            for param in environment_params:
                values = env_data[param]
                stats[f"avg_{param}"] = mean(values)
                stats[f"var_{param}"] = variance(values)
                stats[f"max_{param}"] = max(values)
                stats[f"min_{param}"] = min(values)

            # 创建并保存MySQL数据记录
            from .models import Data, db

            new_stats = Data(
                device_id=req_data["device_id"], timestamp=req_data["time"], **stats
            )
            db.session.add(new_stats)
            db.session.commit()

            print("统计值计算完成。")

        return respond({"message": "环境数据上传成功"})
    except Exception as e:
        # print(e)
        return respond(
            None, f"数据存储失败: {str(e)}", ERRORCODES.INTERNAL_SERVER_ERROR
        )


@auth_required()
@bp.route("/analysis", methods=["GET"])
def analysis():
    """
    统一的环境数据分析接口
    支持简单分析、异常检测、趋势预测和综合报告生成
    """
    # 获取参数
    device_id = request.args.get("device_id")
    report_type = request.args.get("type", "simple")  # 可选值: simple, anomaly, trend, comprehensive
    time_range = request.args.get("time_range", "7")  # 默认分析最近7天数据

    if not device_id:
        return respond(None, "缺少设备ID参数", ERRORCODES.BAD_REQUEST)

    try:
        # 导入模型
        from .models import Data, AnalysisReport, db
        import datetime

        # 设置时间范围
        end_date = datetime.datetime.now()
        start_date = end_date - datetime.timedelta(days=int(time_range))

        # 环境参数列表
        environment_params = [
            "temperature", "humidity", "fresh_air", "ozone", "nitro_dio", 
            "methanal", "pm2_5", "carb_momo", "bacteria", "radon",
        ]

        # 参数中文名称映射
        param_names = {
            "temperature": "温度", "humidity": "湿度", "fresh_air": "新风量",
            "ozone": "臭氧", "nitro_dio": "二氧化氮", "methanal": "甲醛",
            "pm2_5": "PM2.5", "carb_momo": "一氧化碳", "bacteria": "细菌", "radon": "氡",
        }

        # 准备数据和提示词
        prompt, system_prompt = "", ""
        
        if report_type == "simple":
            # 简单分析只需要最新的统计数据
            latest_stats = Data.query.filter_by(device_id=device_id).order_by(Data.timestamp.desc()).first()
            if not latest_stats:
                return respond(None, "未找到该设备的统计数据", ERRORCODES.NOT_FOUND)
                
            # 构建包含统计数据的请求文本
            stats_text = "环境数据统计信息如下：\n"
            for param in environment_params:
                param_name = param_names.get(param, param)
                stats_text += f"{param_name}：平均值 {getattr(latest_stats, f'avg_{param}', 'N/A'):.2f}, "
                stats_text += f"方差 {getattr(latest_stats, f'var_{param}', 'N/A'):.2f}, "
                stats_text += f"最大值 {getattr(latest_stats, f'max_{param}', 'N/A'):.2f}, "
                stats_text += f"最小值 {getattr(latest_stats, f'min_{param}', 'N/A'):.2f}\n"

            prompt = f"请根据以下数据，分析环境的空气质量：\n{stats_text}"
            system_prompt = "你是一位专业的环境监测数据分析专家，擅长分析空气质量数据并提供专业的改进建议。"
        else:
            # 高级分析需要历史数据
            historical_data = (Data.query.filter_by(device_id=device_id)
                              .filter(Data.timestamp.between(start_date, end_date))
                              .order_by(Data.timestamp.asc()).all())
            if not historical_data:
                return respond(None, "未找到该设备的历史数据", ERRORCODES.NOT_FOUND)
                
            # 构建时间序列数据和检测异常值
            time_series_data, anomalies = {}, {}
            for param in environment_params:
                # 构建时间序列数据
                time_series_data[param] = {
                    "timestamps": [data.timestamp.strftime("%Y-%m-%d %H:%M:%S") for data in historical_data],
                    "avg_values": [getattr(data, f"avg_{param}") for data in historical_data],
                    "max_values": [getattr(data, f"max_{param}") for data in historical_data],
                    "min_values": [getattr(data, f"min_{param}") for data in historical_data],
                    "var_values": [getattr(data, f"var_{param}") for data in historical_data],
                }
                
                # 检测异常值
                avg_values = [getattr(data, f"avg_{param}") for data in historical_data]
                if len(avg_values) > 0:
                    param_mean = mean(avg_values)
                    param_std = variance(avg_values) ** 0.5 if len(avg_values) > 1 else 0
                    
                    # 简单的3-sigma异常检测
                    threshold = 3 * param_std
                    anomaly_indices = [i for i, val in enumerate(avg_values) if abs(val - param_mean) > threshold]
                    
                    if anomaly_indices:
                        anomalies[param] = {
                            "indices": anomaly_indices,
                            "timestamps": [historical_data[i].timestamp.strftime("%Y-%m-%d %H:%M:%S") for i in anomaly_indices],
                            "values": [avg_values[i] for i in anomaly_indices],
                        }
            
            # 根据报告类型构建不同的提示词
            if report_type == "anomaly":
                prompt = f"""请分析以下环境监测数据中的异常情况，并给出可能的原因和建议：
                            1. 设备ID: {device_id}
                            2. 时间范围: 最近{time_range}天
                            3. 检测到的异常:
                            """
                for param, anomaly_data in anomalies.items():
                    prompt += f"\n- {param_names.get(param, param)}异常点: {len(anomaly_data['indices'])}个"
                    for i in range(min(3, len(anomaly_data["indices"]))):
                        prompt += f"\n  * 时间: {anomaly_data['timestamps'][i]}, 值: {anomaly_data['values'][i]:.2f}"
                    if len(anomaly_data["indices"]) > 3:
                        prompt += f"\n  * ... 等{len(anomaly_data['indices']) - 3}个异常点"
                
                prompt += "\n\n请分析这些异常的可能原因（如设备故障或外部环境影响），并给出针对性的建议。"
            
            elif report_type == "trend":
                prompt = f"""请分析以下环境监测数据的趋势，并预测未来可能的变化：
                            1. 设备ID: {device_id}
                            2. 时间范围: 最近{time_range}天
                            3. 各参数趋势概述:
                            """
                for param in environment_params:
                    avg_values = time_series_data[param]["avg_values"]
                    if len(avg_values) > 1:
                        start_val, end_val = avg_values[0], avg_values[-1]
                        change = ((end_val - start_val) / start_val) * 100 if start_val != 0 else 0
                        trend = "上升" if change > 5 else "下降" if change < -5 else "稳定"
                        prompt += f"\n- {param_names.get(param, param)}: {trend}, 变化率 {change:.2f}%"
                
                prompt += "\n\n请分析这些趋势的含义，预测未来可能的变化，并给出相应的建议。"
            
            else:  # comprehensive
                prompt = f"""请根据以下环境监测数据，生成一份综合性报告：
                            1. 设备ID: {device_id}
                            2. 时间范围: 最近{time_range}天
                            3. 数据概览:
                            """
                for param in environment_params:
                    avg_values = time_series_data[param]["avg_values"]
                    if len(avg_values) > 0:
                        prompt += f"\n- {param_names.get(param, param)}: 平均值 {mean(avg_values):.2f}, 最大值 {max(time_series_data[param]['max_values']):.2f}, 最小值 {min(time_series_data[param]['min_values']):.2f}"
                
                prompt += "\n\n4. 异常情况:"
                if anomalies:
                    for param, anomaly_data in anomalies.items():
                        prompt += f"\n- {param_names.get(param, param)}异常点: {len(anomaly_data['indices'])}个"
                else:
                    prompt += "\n- 未检测到明显异常"
                
                prompt += "\n\n请提供以下内容：\n1. 环境质量综合评估\n2. 异常原因分析\n3. 未来趋势预测\n4. 改进建议\n5. 总结"
            
            system_prompt = "你是一位专业的环境监测数据分析专家，擅长分析空气质量数据，检测异常，预测趋势，并提供专业的改进建议。"
        
        # 调用DeepSeek API
        client = OpenAI(
            api_key=os.getenv("DEEPSEEK_API_KEY_lbwnb"),
            base_url="https://api.deepseek.com",
        )
        
        response = client.chat.completions.create(
            model="deepseek-chat",
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": prompt},
            ],
            stream=False,
        )
        
        analysis_result = response.choices[0].message.content
        
        # 保存分析报告到数据库
        current_time = datetime.datetime.now()
        new_report = AnalysisReport(
            device_id=device_id,
            report_type=report_type,
            time_range=int(time_range),
            content=analysis_result,
            created_at=current_time,
        )
        db.session.add(new_report)
        db.session.commit()
        
        return respond({
            "report_type": report_type,
            "device_id": device_id,
            "time_range": time_range,
            "analysis": analysis_result,
            "generated_at": current_time.strftime("%Y-%m-%d %H:%M:%S"),
            "report_id": new_report.id,
        })
        
    except Exception as e:
        print(e)
        return respond(None, f"数据分析失败: {str(e)}", ERRORCODES.INTERNAL_SERVER_ERROR)
